package com.tedu.udm.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tedu.udm.ex.ServiceException;
import com.tedu.udm.mapper.*;
import com.tedu.udm.pojo.dto.UserAddNewDTO;
import com.tedu.udm.pojo.dto.UserLoginDTO;
import com.tedu.udm.pojo.dto.UserUpdateClassDTO;
import com.tedu.udm.pojo.entity.Classes;
import com.tedu.udm.pojo.vo.*;
import com.tedu.udm.pojo.entity.User;
import com.tedu.udm.pojo.entity.UserRole;
import com.tedu.udm.service.IUserService;
import com.tedu.udm.shiro.BCryptPasswordEncoder;
import com.tedu.udm.web.ServiceCode;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.*;


/**
 * 处理用户数据的业务实现类
 *
 * @author java@tedu.cn
 * @version 0.0.1
 */
@Slf4j
@Service
public class UserServiceImpl implements IUserService {
    @Value("${udm.jwt.secret-key}")
    private String secretKey;
    @Value("${udm.jwt.duration-in-minute}")
    private long durationInMinute;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private ClassMapper classMapper;
    @Autowired
    private UserTeamMapper userTeamMapper;

    public UserServiceImpl() {
        log.info("创建业务对象：UserServiceImpl");
    }

    public String login(UserLoginDTO userLoginDTO){
        log.debug("开始处理登录业务");
        //创建一个shiro的Subject对象，利用这个对象来完成用户的登录认证
        Subject subject = SecurityUtils.getSubject();
        String loginUsername =userLoginDTO.getUsername();
        // 对用户密码进行加密，并生成认证使用的JWTToken
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("username",loginUsername);
        User user = userMapper.selectOne(wrapper);
        //获取数据库中
        if (user==null) {
            String message = "登录失败，用户名或密码错！";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_UNAUTHORIZED,message);
        }

        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        if (!passwordEncoder.matches(userLoginDTO.getPassword(),user.getPassword())) {
            String message = "登录失败，用户名或密码错！";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_UNAUTHORIZED,message);
        }

        log.debug("用户认证成功！");

        Map<String, Object> claims = new HashMap<>();
        //获取用户数据库权限
        UserLoginInfoVO info = userMapper.getLoginInfoByUsername(userLoginDTO.getUsername());
        log.debug("初始的权限信息：{}",info.getPermissions());
        List<String> permissions= info.getPermissions();
        List<Map<String,String>> list = new ArrayList<>();
        for (String permission:permissions) {
            Map<String,String> permissionMap = new HashMap<>();
            permissionMap.put("authority",permission);
            list.add(permissionMap);
        }
        log.debug("数组的权限信息：{}",list);
        String authoritiesJsonString = JSON.toJSONString(list);
        log.debug("初始的权限信息：{}",authoritiesJsonString);

        // 生成JWT数据时，需要填充装到JWT中的数据
        claims.clear();
        // claims.put("id", 9527);
        claims.put("id",info.getId());
        claims.put("username", info.getUsername());
        claims.put("nickname",info.getNickname());
        claims.put("authoritiesJsonString",authoritiesJsonString);
        // 以下是生成JWT的固定代码
        Date date = new Date(System.currentTimeMillis() + durationInMinute * 60 * 1000L);
        String jwt = Jwts.builder()
                // Header
                .setHeaderParam("alg", "HS256")
                .setHeaderParam("typ", "JWT")
                // Payload
                .setClaims(claims)
                // Signature
                .setExpiration(date)
                .signWith(SignatureAlgorithm.HS256,secretKey)
                .compact();
        log.debug("生成的JWT：{}", jwt);
        User addLoginCount = new User();
        addLoginCount.setId(user.getId());
        addLoginCount.setLoginCount(user.getLoginCount()+1);
        int rows = userMapper.updateById(addLoginCount);
        if (rows != 1) {
            // 是：抛出异常
            String message = "服务器忙，请稍后再试！";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }
        return jwt;
        /*if(!subject.isAuthenticated()){
            //判断当前用户是否已经认证过，如果已经认证过着不需要认证;如果没有认证过则完成认证
        }*/
    }

    @Override
    public void addNew(UserAddNewDTO userAddNewDTO) {
        log.debug("开始处理【添加用户】的业务，参数：{}", userAddNewDTO);

        log.debug("即将检查用户名是否被占用……");
        {
            // 从参数对象中获取username
            String username = userAddNewDTO.getUsername();
            // 调用adminMapper的countByUsername()方法执行统计查询
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.eq("username",username);
            int count = userMapper.selectCount(wrapper);
            // 判断统计结果是否不等于0
            if (count != 0) {
                // 是：抛出异常
                String message = "添加用户失败，用户名【" + username + "】已经被占用！";
                log.debug(message);
                throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
            }
        }

        log.debug("即将检查手机号码是否被占用……");
        {
            // 从参数对象中获取手机号码
            String phone = userAddNewDTO.getPhone();
            // 调用adminMapper的countByPhone()方法执行统计查询
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.eq("phone",phone);
            int count = userMapper.selectCount(wrapper);
            // 判断统计结果是否不等于0
            if (count != 0) {
                // 是：抛出异常
                String message = "添加用户失败，手机号码【" + phone + "】已经被占用！";
                log.debug(message);
                throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
            }
        }

        log.debug("即将检查电子邮箱是否被占用……");
        {
            // 从参数对象中获取电子邮箱
            String email = userAddNewDTO.getEmail();
            // 调用adminMapper的countByEmail()方法执行统计查询
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.eq("email",email);
            int count = userMapper.selectCount(wrapper);
            // 判断统计结果是否不等于0
            if (count != 0) {
                // 是：抛出异常
                String message = "添加用户失败，电子邮箱【" + email + "】已经被占用！";
                log.debug(message);
                throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
            }
        }

        // 创建User对象
        User user = new User();
        // 通过BeanUtils.copyProperties()方法将参数对象的各属性值复制到User对象中
        BeanUtils.copyProperties(userAddNewDTO, user);

        //BCri
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encodedPassword = passwordEncoder.encode(user.getPassword());

        //替换密文
        user.setPassword(encodedPassword);
        // 补全User对象中的属性值：loginCount >>> 0
        user.setLoginCount(0);
        // 调用userMapper的insert()方法插入数据
        log.debug("即将插入用户数据，参数：{}", user);
        int rows = userMapper.insert(user);
        // 判断插入数据的结果是否符合预期
        if (rows != 1) {
            String message = "添加用户失败，服务器忙，请稍后再次尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        }
        // 插入管理员与角色关联的数据
        List<Long> roleIds = new ArrayList<>();
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("role_name","学员");
        Long roleId = roleMapper.selectOne(wrapper).getId();
        roleIds.add(roleId);
        if (userAddNewDTO.getIsTeacher()==1) {
            wrapper = new QueryWrapper();
            wrapper.eq("role_name","老师");
            roleId = roleMapper.selectOne(wrapper).getId();
            roleIds.add(roleId);
        }
        Collection<UserRole> userRoles= new ArrayList<>();
        for (Long role:roleIds) {
            UserRole userRole = new UserRole();
            userRole.setUserId(user.getId());
            userRole.setRoleId(role);
            userRoles.add(userRole);
        }
        rows = userRoleMapper.insertBatchSomeColumn(userRoles);
        if (rows < 1) {
            String message = "添加用户失败，服务器忙，请稍后再次尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        }
    }

    @Override
    public void delete(Long id) {
        log.debug("开始处理【删除用户】的业务，参数：{}", id);
        // id值为1的用户不允许被删除
        if (id == 1) {
            // 是：抛出异常（ERR_NOT_FOUND）
            String message = "删除用户失败，尝试删除的用户数据不存在！";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        // 调用adminMapper的AdminStandardVO getStandardById(Long id)方法执行查询
        User queryResult = userMapper.selectById(id);
        // 判断查询结果是否为null
        if (queryResult == null) {
            // 是：抛出异常（ERR_NOT_FOUND）
            String message = "删除用户失败，尝试删除的用户数据不存在！";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        // 调用userMapper的int deleteById(Long id)执行删除，并获取返回的行数
        int rows = userMapper.deleteById(id);
        // 判断返回的行数是否不为1
        if (rows != 1) {
            // 是：抛出异常（ERR_DELETE：服务器忙）
            String message = "删除用户失败，服务器忙，请稍后再尝试！";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_DELETE, message);
        }
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("user_id",id);
        rows = userRoleMapper.delete(wrapper);
        if (rows < 1) {
            // 是：抛出异常（ERR_DELETE：服务器忙）
            String message = "删除用户失败，服务器忙，请稍后再尝试！";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_DELETE, message);
        }

    }

    @Override
    public void updateClass(Long id, UserUpdateClassDTO userUpdateClassDTO) {
        log.debug("开始处理【修改用户班级】的业务，参数：{}和{}", id,userUpdateClassDTO);

        log.debug("检查修改班级的信息是否存在！");
        Classes classes = classMapper.selectById(userUpdateClassDTO.getClassId());
        if (classes == null) {
            // 是：抛出异常（ERR_NOT_FOUND）
            String message = "修改用户班级失败，尝试修改的班级数据不存在！";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        log.debug("检查通过，准备修改用户班级信息！");
        User user = new User();
        BeanUtils.copyProperties(userUpdateClassDTO,user);
        int rows = userMapper.updateById(user);
        if (rows != 1) {
            String message = "修改用户班级，服务器忙，请稍后再次尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }
    }

    @Override
    public void setEnable(Long id) {
        updateEnableById(id, 1);
    }

    @Override
    public void setDisable(Long id) {
        updateEnableById(id, 0);
    }

    @Override
    public List<UserListItemVO> list() {
        log.debug("开始处理【查询用户列表】的业务，无参数");
        List<User> users = userMapper.selectList(null);
        List<UserListItemVO> list = new ArrayList<>();
        for (User user: users) {
            if (user.getId()!=1){
                UserListItemVO userListItemVO = new UserListItemVO();
                BeanUtils.copyProperties(user,userListItemVO);
                list.add(userListItemVO);
            }
        }
        return list;
    }

    @Override
    public List<UserListTeacherVO> listByTeacher(){
        log.debug("开始处理【查询用户列表】的业务，无参数");
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("is_teacher",1);
        List<User> users = userMapper.selectList(wrapper);
        List<UserListTeacherVO> list = new ArrayList<>();
        for (User user : users) {
            if (user.getId() != 1){
                UserListTeacherVO userListTeacherVO = new UserListTeacherVO();
                BeanUtils.copyProperties(user,userListTeacherVO);
                list.add(userListTeacherVO);
            }
        }
        return list;
    }


    @Override
    public List<UserListItemVO> listBySearch(String search){
        log.debug("开始处理【查询用户列表】的业务，无参数");
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.like("nickname",search);
        wrapper.orderByDesc("create_date");
        List<User> users = userMapper.selectList(wrapper);
        List<UserListItemVO> list = new ArrayList<>();
        for (User user : users) {
            if (user.getId() != 1){
                UserListItemVO userListItemVO = new UserListItemVO();
                BeanUtils.copyProperties(user,userListItemVO);
                list.add(userListItemVO);
            }
        }
        return list;
    }

    public List<UserListItemVO> listByClassId(Long id){
        log.debug("开始处理【查询班级学员】的业务，无参数");
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("class_id",id);
        List<User> users = userMapper.selectList(wrapper);
        List<UserListItemVO> list = new ArrayList<>();
        for (User user: users) {
            if (user.getId()!=1){
                UserListItemVO userListItemVO = new UserListItemVO();
                BeanUtils.copyProperties(user,userListItemVO);
                list.add(userListItemVO);
            }
        }
        return list;
    }

    public List<UserListItemVO> listByClassIdNoTeam(Long id){
        log.debug("开始处理【查询用户列表】的业务，无参数");
        List<UserListItemVO> listByClassId = listByClassId(id);
        List<UserTeamListVO> userTeamListVOs = userTeamMapper.listByClassId(id);
        List<UserListItemVO> listNoTeam = new ArrayList<>();
        for (UserListItemVO list:listByClassId) {
            boolean isHave = false;
            for (UserTeamListVO userTeam:userTeamListVOs) {
                if (list.getId().equals(userTeam.getUserId())){
                    isHave = true;
                    System.out.println(isHave);
                    break;
                }
            }
            if (!isHave) {
                listNoTeam.add(list);
            }
        }
        return listNoTeam;
    }

    public List<UserListTeamVO> listByTeamId(Long id){
        log.debug("开始处理【查询小组学员】的业务，无参数");
        List<UserListTeamVO> list = userMapper.listByTeamId(id);
        return list;
    }

    private void updateEnableById(Long id, Integer enable) {
        String[] tips = {"禁用", "启用"};
        log.debug("开始处理【{}用户】的业务，参数：{}", tips[enable], id);

        // 判断参数id是否为1
        if (id == 1) {
            String message = tips[enable] + "用户失败，尝试访问的数据不存在！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        // 检查尝试访问的数据是否存在
        System.out.println(id);
        User queryResult = userMapper.selectById(id);
        System.out.println(queryResult);
        if (queryResult == null) {
            String message = tips[enable] + "用户失败，查不到用户的数据不存在！";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        // 判断状态是否冲突（当前已经是目标状态）
        if (queryResult.getEnable().equals(enable)) {
            String message = tips[enable] + "用户失败，用户账号已经处于" + tips[enable] + "状态！";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        // 准备执行更新
        User user = new User();
        user.setId(id);
        user.setEnable(enable);
        int rows = userMapper.updateById(user);
        if (rows != 1) {
            String message = tips[enable] + "用户失败，服务器忙，请稍后再次尝试！";
            log.warn(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }
    }

}